﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SecurityApi.DataAccess
{
    public class EnterpriseUserRepository : BaseRepository
    {
        public IQueryable<SecurityApi.Model.EnterpriseUser> GetAll()
        {
            var query = from u in _context.EnterpriseUsers
                        join e in _context.Enterprises on u.EnterpriseId equals e.EnterpriseId
                        select new SecurityApi.Model.EnterpriseUser
                        {
                            UserId = u.UserId,
                            UserName = u.UserName,
                            Enterprise = new Model.Enterprise{Id = e.EnterpriseId,Name=e.Name},
                            EnterpriseId = e.EnterpriseId,
                            FirstName = u.FirstName,
                            LastName = u.LastName,
                            MiddleName = u.MiddleName,
                            Password = u.Password,
                            PasswordSalt = u.PasswordSalt
                        };
            return query;
        }

        public IQueryable<SecurityApi.Model.EnterpriseUser> GetApplicationUsers(int appId)
        {
            var query = from u in _context.EnterpriseUsers
                        join e in _context.Enterprises on u.EnterpriseId equals e.EnterpriseId
                        join a in _context.UserApplications on u.UserId equals a.UserId
                        where a.ApplicationId == appId
                        select new SecurityApi.Model.EnterpriseUser
                        {
                            UserId = u.UserId,
                            UserName = u.UserName,
                            Enterprise = new Model.Enterprise { Id = e.EnterpriseId, Name = e.Name },
                            EnterpriseId = e.EnterpriseId,
                            FirstName = u.FirstName,
                            LastName = u.LastName,
                            MiddleName = u.MiddleName,
                            Password = u.Password,
                            PasswordSalt = u.PasswordSalt

                        };
            return query;
        }


        public IQueryable<SecurityApi.Model.Application> GetUserApplications(string userName, int enterpriseId = 1)
        {
            var query = from u in _context.EnterpriseUsers
                        join ua in _context.UserApplications on u.UserId equals ua.UserId
                        join a in _context.Applications on ua.ApplicationId equals a.ApplicationId
                        where u.UserName == userName && u.EnterpriseId == enterpriseId
                        select new SecurityApi.Model.Application
                        {
                            ApplicationId = a.ApplicationId,
                            Title = a.Title,
                            Name = a.Name,
                            Active = a.Active,
                            Area = a.Area,
                            DefaltController = a.DefaltController,
                            DefaltAction = a.DefaltAction,
                        };

            return query;
        }

        public EnterpriseUser GetUserById(int id)
        {
            EnterpriseUser efUser = _context.EnterpriseUsers
                    .Include("UserClaims")
                    .Where(p => p.UserId == id).SingleOrDefault();
            foreach (UserClaim uc in efUser.UserClaims)
            {
                uc.ClaimType = _context.ClaimTypes.Where(p => p.ClaimTypeId == uc.ClaimTypeId).SingleOrDefault();
                uc.Resource = _context.Resources.Where(p => p.ResourceId == uc.ResourceId).SingleOrDefault();
            }

            //return efUser;
            return efUser;
        }

        public EnterpriseUser GetUserByUserName(string userName)
        {
            EnterpriseUser efUser = _context.EnterpriseUsers
                    .Include("UserClaims")
                    .Where(p => p.UserName == userName).SingleOrDefault();

            foreach (UserClaim uc in efUser.UserClaims)
            {
                uc.ClaimType = _context.ClaimTypes.Where(p => p.ClaimTypeId == uc.ClaimTypeId).SingleOrDefault();
                uc.Resource = _context.Resources.Where(p => p.ResourceId == uc.ResourceId).SingleOrDefault();
            }

            return efUser;
        }

        public int AddUser(string userName, int enterpriseId=1)
        {
            int userId = -1;

            try
            {
                EnterpriseUser user = new EnterpriseUser();
                user.UserName = userName;
                user.EnterpriseId = enterpriseId;
                user.adt_DateCreated = DateTime.Now;
                _context.EnterpriseUsers.Add(user);
                _context.SaveChanges();
                userId = user.UserId;
            }
            catch (Exception ex)
            {
                userId = -1;
            }

            return userId;
        }

        /// <summary>
        /// TODO: WHen user is removed, lot of other things needs to be cleaned up
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="applicationId"></param>
        /// <returns></returns>
        public bool RemoveUser(string userName, int enterpriseId = 1)
        {
            bool bResult = true;

            try
            {
                EnterpriseUser userClaim = _context.EnterpriseUsers.Where(p => p.UserName == userName && p.EnterpriseId == enterpriseId).SingleOrDefault();
                if (null != userClaim)
                {
                    _context.EnterpriseUsers.Remove(userClaim);
                    _context.SaveChanges();
                }
                else
                {
                    bResult = false;
                }
            }
            catch (Exception ex)
            {
                bResult = false;
            }

            return bResult;
        }

        public bool AddClaimToUser(int userId,int resourceId,int claimTypeId)
        {
            bool bResult = true;

            try
            {
                UserClaim userClaim = new UserClaim();
                userClaim.UserId = userId;
                userClaim.ResourceId = resourceId;
                userClaim.ClaimTypeId = claimTypeId;
                userClaim.adt_DateCreated = DateTime.Now;
                _context.UserClaims.Add(userClaim);
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                bResult = false;
            }

            return bResult;
        }

        public bool RemoveUserClaim(int userId, int resourceId, int claimTypeId)
        {
            bool bResult = true;

            try
            {
                UserClaim userClaim = _context.UserClaims.Where(p => p.UserId == userId && p.ResourceId == resourceId && p.ClaimTypeId == claimTypeId).SingleOrDefault();

                if (null != userClaim)
                {
                    _context.UserClaims.Remove(userClaim);
                    _context.SaveChanges();
                }
                else
                {
                    bResult = false;
                }
            }
            catch (Exception ex)
            {
                bResult = false;
            }

            return bResult;
        }


        public bool UpdatePasswordInformation(string userName, string password,string salt, int enterpriseId = 1)
        {
            bool bResult = true;

            try
            {
                EnterpriseUser efUser = _context.EnterpriseUsers.Where(p => p.UserName == userName && p.EnterpriseId == enterpriseId).SingleOrDefault();
                if (null != efUser)
                {
                    efUser.Password = password;
                    efUser.PasswordSalt = salt;
                    _context.SaveChanges();
                }
                else
                {
                    bResult = false;
                }
            }
            catch (Exception ex)
            {
                bResult = false;
            }

            return bResult;
        }

    }
}
